Function Get-ComputerEvent($providerName,$computerName,$startTime,$endTime,$exportPath,$excludedEventIds)
{
    Write-Host "Capturing $providerName on $computerName"
    if($excludedEventIds -eq $null)
    {
        Get-WinEvent -FilterHashtable @{ProviderName=$providerName;StartTime=$startTime;EndTime=$endTime;Level=1,2,3} -ComputerName $computerName -ErrorAction SilentlyContinue 
    }
    else
    {
        Get-WinEvent -FilterHashtable @{ProviderName=$providerName;StartTime=$startTime;EndTime=$endTime;Level=1,2,3} -ComputerName $computerName -ErrorAction SilentlyContinue| Where-Object {$_.ID -notin $excludedEventIds} 
    }
}

Function Normalize-Event()
{
    begin
    {
    }
    process
    {
        $event=$_   
        $normalizedEvent=New-Object -TypeName PSObject

        $normalizedEvent | Add-Member -MemberType NoteProperty -Name MachineName -Value $event.MachineName
        $normalizedEvent | Add-Member -MemberType NoteProperty -Name ProviderName -Value $event.ProviderName
        $normalizedEvent | Add-Member -MemberType NoteProperty -Name RecordId -Value $event.RecordId
        $normalizedEvent | Add-Member -MemberType NoteProperty -Name Id -Value $event.Id
        $normalizedEvent | Add-Member -MemberType NoteProperty -Name TimeCreated -Value $event.TimeCreated
        $normalizedEvent | Add-Member -MemberType NoteProperty -Name LevelDisplayName -Value $event.LevelDisplayName
        $normalizedEvent | Add-Member -MemberType NoteProperty -Name RawMessage -Value $event.Message.Replace("`r","").Replace("`n","")
        $normalizedEvent | Add-Member -MemberType NoteProperty -Name NormalizedMessage -Value ""

        if($normalizedEvent.RawMessage -like "Cluster resource 'Virtual Machine Configuration *' of type 'Virtual Machine Configuration' in clustered role '*' failed. The error code was '0x43'*")
        {
            $normalizedEvent.NormalizedMessage="Cluster resource 'Virtual Machine Configuration <VMName>' of type 'Virtual Machine Configuration' in clustered role '<VMName>' failed. The error code was '0x43' ('The network name cannot be found.').Based on the failure policies for the resource and role, the cluster service may try to bring the resource online on this node or move the group to another node of the cluster and then restart it." 
        }
        elseif($normalizedEvent.RawMessage -like "Cluster resource 'Virtual Machine Configuration *' of type 'Virtual Machine Configuration' in clustered role '*' failed.*")
        {
            $normalizedEvent.NormalizedMessage="Cluster resource 'Virtual Machine Configuration <VMName>' of type 'Virtual Machine Configuration' in clustered role '<VMName>' failed.Based on the failure policies for the resource and role, the cluster service may try to bring the resource online on this node or move the group to another node of the cluster and then restart it."
        }
        elseif($normalizedEvent.RawMessage -like "Cluster resource 'Virtual Machine *' of type 'Virtual Machine' in clustered role '*' failed. The error code was '0x21' ('The process cannot access the file because another process has locked a portion of the file.').*")
        {
            $normalizedEvent.NormalizedMessage="Cluster resource 'Virtual Machine <VMName>' of type 'Virtual Machine' in clustered role '<VMName>' failed. The error code was '0x21' ('The process cannot access the file because another process has locked a portion of the file.').Based on the failure policies for the resource and role, the cluster service may try to bring the resource online on this node or move the group to another node of the cluster and then restart it."
        }
        elseif($normalizedEvent.RawMessage -like "Cluster resource 'Virtual Machine *' of type 'Virtual Machine' in clustered role '*' failed.*")
        {
            $normalizedEvent.NormalizedMessage="Cluster resource 'Virtual Machine <VMName>' of type 'Virtual Machine' in clustered role '<VMName>' failed."
        }
        elseif($normalizedEvent.RawMessage -like "The pending move for the role '*' did not complete.*")
        {
            $normalizedEvent.NormalizedMessage="The pending move for the role '<VMName>' did not complete."
        }
        elseif($normalizedEvent.RawMessage -like "The Cluster service failed to bring clustered role '*' completely online or offline.*")
        {
            $normalizedEvent.NormalizedMessage="The Cluster service failed to bring clustered role '<VMName>' completely online or offline. One or more resources may be in a failed state. This may impact the availability of the clustered role."
        }
        elseif($normalizedEvent.RawMessage -like "Cluster resource 'Virtual Machine *' in clustered role  '*' has received a critical state notification.  For a virtual machine this indicates that a critical network of the virtual machine is in an unhealthy state.*")
        {
            $normalizedEvent.NormalizedMessage="Cluster resource 'Virtual Machine <VMName>' in clustered role  '<VMName>' has received a critical state notification.  For a virtual machine this indicates that a critical network of the virtual machine is in an unhealthy state."
        }
        elseif($normalizedEvent.RawMessage -like "``[RCM``] Queueing immediate delay restart of resource Virtual Machine Configuration * in 500 ms.*")
        {
            $normalizedEvent.NormalizedMessage="[RCM] Queueing immediate delay restart of resource Virtual Machine Configuration <VMName> in 500 ms."
        }
        elseif($normalizedEvent.RawMessage -like "``[RCM``] Queueing immediate delay restart of resource Virtual Machine * in 500 ms.*")
        {
            $normalizedEvent.NormalizedMessage="[RCM] Queueing immediate delay restart of resource Virtual Machine <VMName> in 500 ms."
        }
        elseif($normalizedEvent.RawMessage -like "``[RCM``] HandleMonitorReply: ONLINERESOURCE for 'Virtual Machine Configuration *', gen(*) result 5018/67.*")
        {
            $normalizedEvent.NormalizedMessage="[RCM] HandleMonitorReply: ONLINERESOURCE for 'Virtual Machine Configuration <VMName>', gen(*) result 5018/67."
        }
        elseif($normalizedEvent.RawMessage -like "``[MRR``] Node 2: insert request record for RID * logged due to expiring*")
        {
            $normalizedEvent.NormalizedMessage="[MRR] Node 2: insert request record for RID <ID> logged due to expiring"
        }
        elseif($normalizedEvent.RawMessage -like "``[MRR``] SendRequest(<message action='/rcm/mrr/GimProvisionalPlacementDecisionRemove' GemId='0' target='RCMA' sender='-1'mrr='*'/>) NumDest:65 logged due to expiring*")
        {
            $normalizedEvent.NormalizedMessage="[MRR] SendRequest(<message action='/rcm/mrr/GimProvisionalPlacementDecisionRemove' GemId='0' target='RCMA' sender='-1'mrr='<ID>'/>) NumDest:65 logged due to expiring"
        }
        elseif($normalizedEvent.RawMessage -like "``[PM``] Couldn't find both the interfaces (*,*) for probe route. Not adding probe route*")
        {
            $normalizedEvent.NormalizedMessage="[PM] Couldn't find both the interfaces (<GUID>,<GUID>) for probe route. Not adding probe route"
        }
        elseif($normalizedEvent.RawMessage -like "``[RCM``] Failing over group *, failoverCount *, last time *")
        {
            $normalizedEvent.NormalizedMessage="[RCM] Failing over group <VMName>, failoverCount <Count>, last time <Date>."
        }
        elseif($normalizedEvent.RawMessage -like "``[RHS``] Resource Virtual Machine Configuration * IsAlive has indicated failure.*")
        {
            $normalizedEvent.NormalizedMessage="[RHS] Resource Virtual Machine Configuration <VMName> IsAlive has indicated failure."
        }
        elseif($normalizedEvent.RawMessage -like "``[RHS``] Resource Virtual Machine * IsAlive has indicated failure.*")
        {
            $normalizedEvent.NormalizedMessage="[RHS] Resource Virtual Machine <VMName> IsAlive has indicated failure."
        }
        elseif($normalizedEvent.RawMessage -like "``[RHS``] Resource Virtual Machine * is alive!*")
        {
            $normalizedEvent.NormalizedMessage="[RHS] Resource Virtual Machine <VMName> is alive!"
        }
        elseif($normalizedEvent.RawMessage -like "``[RCM``] rcm::RcmResource::HandleFailure: (Virtual Machine Configuration *)*")
        {
            $normalizedEvent.NormalizedMessage="[RCM] rcm::RcmResource::HandleFailure: (Virtual Machine Configuration <VMName>)"
        }
        elseif($normalizedEvent.RawMessage -like "``[RCM``] rcm::RcmResource::HandleFailure: (Virtual Machine *)*")
        {
            $normalizedEvent.NormalizedMessage="[RCM] rcm::RcmResource::HandleFailure: (Virtual Machine <VMName>)"
        }
        elseif($normalizedEvent.RawMessage -like "``[RES``] Physical Disk: HardDiskpIsFileCSVFile(): Failed to execute DeviceIoControl for *, status 50*")
        {
            $normalizedEvent.NormalizedMessage="[RES] Physical Disk: HardDiskpIsFileCSVFile(): Failed to execute DeviceIoControl for <VHDXPath>, status 50"
        }
        elseif($normalizedEvent.RawMessage -like "``[RES``] Virtual Machine <Virtual Machine *>: 'Virtual Machine *' failed to terminate.*")
        {
            $normalizedEvent.NormalizedMessage="[RES] Virtual Machine <Virtual Machine <VMName>>: 'Virtual Machine <VMName>' failed to terminate."
        }
        elseif($normalizedEvent.RawMessage -like "``[RES``] Virtual Machine <Virtual Machine *>: Aborting the Live Migration because the destination '*' does not have all monitored Hyper-V connections in connected state.*")
        {
            $normalizedEvent.NormalizedMessage="[RES] Virtual Machine <Virtual Machine <VMName>>: Aborting the Live Migration because the destination '<HostName>' does not have all monitored Hyper-V connections in connected state."
        }
        elseif($normalizedEvent.RawMessage -like "``[RES``] Virtual Machine <Virtual Machine *>: Live migration of 'Virtual Machine *' failed.'Virtual Machine *' failed to fixup network settings. Verify VM settings and update them as necessary.*")
        {
            $normalizedEvent.NormalizedMessage="[RES] Virtual Machine <Virtual Machine <VMName>>: Live migration of 'Virtual Machine <VMName>' failed.'Virtual Machine <VMName>' failed to fixup network settings. Verify VM settings and update them as necessary."
        }
        elseif($normalizedEvent.RawMessage -like "``[RES``] Virtual Machine Configuration <Virtual Machine Configuration *>: 'Virtual Machine Configuration *' failed to register the virtual machine with the virtual machine management service.The Virtual Machine Management Service failed to register the configuration for the virtual machine '*' at '*': The network name cannot be found.*")
        {
            $normalizedEvent.NormalizedMessage="[RES] Virtual Machine Configuration <Virtual Machine Configuration <VMName>>: 'Virtual Machine Configuration <VMName>' failed to register the virtual machine with the virtual machine management service.The Virtual Machine Management Service failed to register the configuration for the virtual machine '<VMGUID>' at '<VMConfigPath>': The network name cannot be found. (0x80070043)."
        }
        elseif($normalizedEvent.RawMessage -like "'Virtual Machine Configuration *' failed to register the virtual machine with the virtual machine management service.*")
        {
            $normalizedEvent.NormalizedMessage="'Virtual Machine Configuration <VMName>' failed to register the virtual machine with the virtual machine management service."
        }
        elseif($normalizedEvent.RawMessage -like "``[RHS``] Online for resource Virtual Machine Configuration * failed.*")
        {
            $normalizedEvent.NormalizedMessage="[RHS] Online for resource Virtual Machine Configuration <VMName> failed."
        }
        elseif($normalizedEvent.RawMessage -like "``[RHS``] Resource Virtual Machine * has cancelled offline with error code 1222.*")
        {
            $normalizedEvent.NormalizedMessage="[RHS] Resource Virtual Machine <VMName> has cancelled offline with error code 1222."
        }
        elseif($normalizedEvent.RawMessage -like "The path * is on an SMB path not managed by the cluster.  Since this path is not managed by the cluster ensure that the SMB path will available for the virtual machine.*")
        {
            $normalizedEvent.NormalizedMessage="The path <VHDXPath> is on an SMB path not managed by the cluster.  Since this path is not managed by the cluster ensure that the SMB path will available for the virtual machine."
        }
        elseif($normalizedEvent.RawMessage -like "Failed to open configuration file 'C:\*.xml', the configuration store is disabled because of earlier access failures.*")
        {
            $normalizedEvent.NormalizedMessage="Failed to open configuration file '<LocalPathToConfigFile', the configuration store is disabled because of earlier access failures."
        }
        elseif($normalizedEvent.RawMessage -like "'Virtual Machine Configuration <VMName>' failed to register the virtual machine with the virtual machine management service.*")
        {
            $normalizedEvent.NormalizedMessage="'Virtual Machine Configuration <VMName>' failed to register the virtual machine with the virtual machine management service."
        }
        elseif($normalizedEvent.RawMessage -like "'Virtual Machine *' failed to start.*")
        {
            $normalizedEvent.NormalizedMessage="'Virtual Machine <VMName>' failed to start."
        }
        elseif($normalizedEvent.RawMessage -like "'Virtual Machine *' failed to terminate.*")
        {
            $normalizedEvent.NormalizedMessage="'Virtual Machine <VMName>' failed to terminate."
        }
        elseif($normalizedEvent.RawMessage -like "Live migration of 'Virtual Machine *' failed.*")
        {
            $normalizedEvent.NormalizedMessage="Live migration of 'Virtual Machine <VMName>' failed."
        }
        elseif($normalizedEvent.RawMessage -like "'Virtual Machine *' failed to fixup network settings. Verify VM settings and update them as necessary.*")
        {
            $normalizedEvent.NormalizedMessage="'Virtual Machine <VMName>' failed to fixup network settings. Verify VM settings and update them as necessary."
        }
        elseif($normalizedEvent.RawMessage -like "Live migration of 'Virtual Machine *' failed.'Virtual Machine *' failed to fixup network settings. Verify VM settings and update them as necessary.*")
        {
            $normalizedEvent.NormalizedMessage="Live migration of 'Virtual Machine <VMName>' failed.'Virtual Machine <VMName>' failed to fixup network settings. Verify VM settings and update them as necessary."
        }
        elseif($normalizedEvent.RawMessage -like "'Virtual Machine Configuration *' failed to register the virtual machine with the virtual machine management service.The Virtual Machine Management Service failed to register the configuration for the virtual machine '*' at '*': The network name cannot be found. (0x80070043). If the virtual machine is managed by a failover cluster, ensure that the file is located at a path that is accessible to other nodes of the cluster.Failed to open configuration file '*', the configuration store is disabled because of earlier access failures.*")
        {
            $normalizedEvent.NormalizedMessage="'Virtual Machine Configuration <VMName>' failed to register the virtual machine with the virtual machine management service.The Virtual Machine Management Service failed to register the configuration for the virtual machine '<VMGUID>' at '<VMConfigPath>': The network name cannot be found. (0x80070043). If the virtual machine is managed by a failover cluster, ensure that the file is located at a path that is accessible to other nodes of the cluster.Failed to open configuration file '<VMLocalConfigPath>', the configuration store is disabled because of earlier access failures."
        }
        elseif($normalizedEvent.RawMessage -like "Error opening handle for initiator. Initiator: {*}. Hostname: * File: *. Error: A file cannot be opened because the share access flags are incompatible..*")
        {
            $normalizedEvent.NormalizedMessage="Error opening handle for initiator. Initiator: {<InitiatorGUID>}. Hostname: <ClientHostName> File: <FilePath>. Error: A file cannot be opened because the share access flags are incompatible.."
        }
        elseif($normalizedEvent.RawMessage -like "Error opening handle for initiator. Initiator: {*}. Hostname: *. File: *. Error: A requested file lock cannot be granted due to other existing locks*")
        {
            $normalizedEvent.NormalizedMessage="Error opening handle for initiator. Initiator: {<InitiatorGUID>}. Hostname: <ClientHostName>. File: <FilePath>. Error: A requested file lock cannot be granted due to other existing locks"
        }
        elseif($normalizedEvent.RawMessage -like "Error while mounting Shared VHDX file. File: *. Error: A file cannot be opened because the share access flags are incompatible..*")
        {
            $normalizedEvent.NormalizedMessage="Error while mounting Shared VHDX file. File: <FilePath>. Error: A file cannot be opened because the share access flags are incompatible.."
        }
        elseif($normalizedEvent.RawMessage -like "Error while mounting Shared VHDX file. File: *. Error: A requested file lock cannot be granted due to other existing locks..*")
        {
            $normalizedEvent.NormalizedMessage="Error while mounting Shared VHDX file. File: <FilePath>. Error: A requested file lock cannot be granted due to other existing locks.."
        }
        elseif($normalizedEvent.RawMessage -like "Shared VHDX file IO took longer than 15000 ms. File *. SCSI operation: 0x9E. Operation time: * ms.*")
        {
            $normalizedEvent.NormalizedMessage="Shared VHDX file IO took longer than 15000 ms. File <FilePath>. SCSI operation: 0x9E. Operation time: * ms."
        }
        elseif($normalizedEvent.RawMessage -like "Error reading metadata from Shared VHDX File. File: *. Error: The object was not found..*")
        {
            $normalizedEvent.NormalizedMessage="Error reading metadata from Shared VHDX File. File: <FilePath>. Error: The object was not found.."
        }
        elseif($normalizedEvent.RawMessage -like "Error writing metadata to Shared VHDX file. File: *. Error: An operation failed because the disk was full.If this is a thinly provisioned volume the physical storage backing this volume has been exhausted..*")
        {
            $normalizedEvent.NormalizedMessage="Error writing metadata to Shared VHDX file. File: <FilePath>. Error: An operation failed because the disk was full.If this is a thinly provisioned volume the physical storage backing this volume has been exhausted.."
        }
        elseif($normalizedEvent.RawMessage -like "'*': Attachment '*' failed to open because of error: 'The process cannot access the file because another process has locked a portion of the file.' (*). (Virtual machine ID *)*")
        {
            $normalizedEvent.NormalizedMessage="'<VMName>': Attachment '<FilePath>' failed to open because of error: 'The process cannot access the file because another process has locked a portion of the file.' (7864368). (Virtual machine ID 66260D0D-7F9A-4D30-AF74-E62353070CC2)"
        }
        elseif($normalizedEvent.RawMessage -like "'*' encountered an error while calculating the size of the disk chain for '*'. The error was: 'The process cannot access the file because another process has locked a portion of the file.' (*). Maximum disk metric will not be updated for the current disk. (Virtual machine ID *)*")
        {
            $normalizedEvent.NormalizedMessage="'<VMName>' encountered an error while calculating the size of the disk chain for '<FilePath>'. The error was: 'The process cannot access the file because another process has locked a portion of the file.' (<Number>). Maximum disk metric will not be updated for the current disk. (Virtual machine ID <VMGUID>)"
        }
        elseif($normalizedEvent.RawMessage -like "'': Attachment '*' not found. Error: 'The system cannot find the file specified.' (0x80070002). (Virtual machine ID )*")
        {
            $normalizedEvent.NormalizedMessage="'': Attachment '<FilePath>' not found. Error: 'The system cannot find the file specified.' (0x80070002). (Virtual machine ID )"
        }
        elseif($normalizedEvent.RawMessage -like "The dynamic memory balancer could not add memory to the virtual machine '*' because its configured maximum has been reached (Virtual machine ID *).*")
        {
            $normalizedEvent.NormalizedMessage="The dynamic memory balancer could not add memory to the virtual machine '<VMName>' because its configured maximum has been reached (Virtual machine ID <VMGUID>)."
        }
        elseif($normalizedEvent.RawMessage -like "The Virtual Machine Management Service failed to register the configuration for the virtual machine '*' at '*': The network name cannot be found. (0x80070043).*")
        {
            $normalizedEvent.NormalizedMessage="The Virtual Machine Management Service failed to register the configuration for the virtual machine '<VMGUID>' at '<VMConfigPath>': The network name cannot be found. (0x80070043)."
        }
        elseif($normalizedEvent.RawMessage -like "The Virtual Machine Management Service failed to verify that the configuration is registered for the virtual machine '*': The network name cannot be found. (0x80070043).*")
        {
            $normalizedEvent.NormalizedMessage="The Virtual Machine Management Service failed to verify that the configuration is registered for the virtual machine '<VMGUID>': The network name cannot be found. (0x80070043)."
        }
        elseif($normalizedEvent.RawMessage -like "The Virtual Machine Management Service did not find the virtual machine. (Virtual Machine ID *)*")
        {
            $normalizedEvent.NormalizedMessage="The Virtual Machine Management Service did not find the virtual machine. (Virtual Machine ID <VMGUID>)"
        }
        elseif($normalizedEvent.RawMessage -like "The Virtual Machine Management Service failed to start the virtual machine '*': Element not found. (0x80070490).*")
        {
            $normalizedEvent.NormalizedMessage="The Virtual Machine Management Service failed to start the virtual machine '<VMGUID>': Element not found. (0x80070490)."
        }
        elseif($normalizedEvent.RawMessage -like "The Virtual Machine Management Service failed to start the virtual machine '*': The group or resource is not in the correct state to perform the requested operation. (0x8007139F).*")
        {
            $normalizedEvent.NormalizedMessage="The Virtual Machine Management Service failed to start the virtual machine '<VMGUID>': The group or resource is not in the correct state to perform the requested operation. (0x8007139F)."
        }
        elseif($normalizedEvent.RawMessage -like "The Virtual Machine Management Service failed to verify the running state of the virtual machine '*': Element not found. (0x80070490).*")
        {
            $normalizedEvent.NormalizedMessage="The Virtual Machine Management Service failed to verify the running state of the virtual machine '<VMGUID>': Element not found. (0x80070490)."
        }
        elseif($normalizedEvent.RawMessage -like "The client lost its session to the server.Error: {Network Name Not Found}The specified share name cannot be found on the remote server.Server name: *Session ID: **")
        {
            $normalizedEvent.NormalizedMessage="The client lost its session to the server.Error: {Network Name Not Found}The specified share name cannot be found on the remote server.Server name: \<ServerName>Session ID: <SessionId>Guidance:If the server is a Windows Failover Cluster file server, then this message occurs when the file share moves between cluster nodes. There should also be an anti-event 30806 indicating the session to the server was re-established. If the server is not a failover cluster, it is likely that the server was previously online, but it is now inaccessible over the network."
        }
        elseif($normalizedEvent.RawMessage -like "SMB Session Authentication FailureClient Name: \\*Client Address: *User Name: NT AUTHORITY\ANONYMOUS LOGONSession ID: *Status: {Access Denied}A process has requested access to an object, but has not been granted those access rights. (0xC0000022)*")
        {
            $normalizedEvent.NormalizedMessage="SMB Session Authentication FailureClient Name: \\<Client>Client Address: <ClientIP>:<Port>User Name: NT AUTHORITY\ANONYMOUS LOGONSession ID: <SessionId>Status: {Access Denied}A process has requested access to an object, but has not been granted those access rights. (0xC0000022)Guidance:You should expect this error when attempting to connect to shares using incorrect credentials.This error does not always indicate a problem with authorization, but mainly authentication. It is more common with non-Windows clients.This error can occur when using incorrect usernames and passwords with NTLM, mismatched LmCompatibility settings between client and server, duplicate Kerberos service principal names, incorrect Kerberos ticket-granting service tickets, or Guest accounts without Guest access enabled"
        }
        elseif($normalizedEvent.RawMessage -like "The server denied anonymous access to the client.Client Name: \\* Client Address: *:*Session ID: *")
        {
            $normalizedEvent.NormalizedMessage="The server denied anonymous access to the client.Client Name: \\<Client> Client Address: <ClientIP>:<Port>Session ID: <SessionId>Guidance:You should expect this error when a client attempts to connect to shares and does not provide any credentials. This indicates that the client is not providing a user name (and domain credentials, if necessary). By default, Windows Server denies anonymous access to shares.This error does not always indicate a problem with authorization, but mainly authentication. It is more common with non-Windows clients."
        }
        elseif($normalizedEvent.RawMessage -like "File system operation has taken longer than expected.Client Name: \\*Client Address: *:*User Name: *Session ID: *Share Name: *Command: *Duration (in milliseconds): *Warning Threshold (in milliseconds): *")
        {
            $normalizedEvent.NormalizedMessage="File system operation has taken longer than expected.Client Name: \\<Client>Client Address: <ClientAddress>:49270User Name: <User>Session ID: <SessionId>Share Name: <FilePath>Command: 11Duration (in milliseconds): <Duration>Warning Threshold (in milliseconds): 120000Guidance:The underlying file system has taken too long to respond to an operation. This typically indicates a problem with the storage and not SMB."
        }
        elseif($normalizedEvent.RawMessage -like "``[DM``] Dm::DmBaseKey::SetValue: (5)' because of 'status'(*)*")
        {
            $normalizedEvent.NormalizedMessage="[DM] Dm::DmBaseKey::SetValue: (5)' because of 'status'(<ISCSIIQN>)"
        }
        elseif($normalizedEvent.RawMessage -like "Remote Desktop Virtualization Host failed to get redirection authentication information from the virtual machine ``[*``] . Hresult: 0x8000FFFF*")
        {
            $normalizedEvent.NormalizedMessage="Remote Desktop Virtualization Host failed to get redirection authentication information from the virtual machine [<VMName>] . Hresult: 0x8000FFFF"
        }
        elseif($normalizedEvent.RawMessage -like "Remote Desktop Virtualization Host failed to set zeroconfig information from the virtual machine ``[*``] . Hresult: 0x80071B6E*")
        {
            $normalizedEvent.NormalizedMessage="Remote Desktop Virtualization Host failed to set zeroconfig information from the virtual machine [<VMName>] . Hresult: 0x80071B6E"
        }
        elseif($normalizedEvent.RawMessage -like "``[RCM``] s_RcmRpcGetResourceState: (5908)' because of ''*' is owned by node *, not *.'*")
        {
            $normalizedEvent.NormalizedMessage="[RCM] s_RcmRpcGetResourceState: (5908)' because of ''<ResourceName>' is owned by node <NodeId>, not <NodeId>.'"
        }
        elseif($normalizedEvent.RawMessage -like "The connection to the share was lost.Error: The network name was deleted.Share name: \*\*`$Session ID: *Tree ID: *")
        {
            $normalizedEvent.NormalizedMessage="The connection to the share was lost.Error: The network name was deleted.Share name: \<Address>\<GUID>`$Session ID: <SessionId>Tree ID: <TreeId>Guidance:If the server is a Windows Failover Cluster file server, then this message occurs when the file share moves between cluster nodes. There should also be an anti-event 30808 indicating the session to the server was re-established. If the server is not a failover cluster, it is likely that the server was previously online, but it is now inaccessible over the network."
        }
        elseif($normalizedEvent.RawMessage -like "The client lost its session to the server.Error: The transport connection is now disconnected.Server name: \*Session ID: *")
        {
            $normalizedEvent.NormalizedMessage="The client lost its session to the server.Error: The transport connection is now disconnected.Server name: \<Address>Session ID: <SessionId>"
        }
        elseif($normalizedEvent.RawMessage -like "The network connection failed.Error: {Device Timeout}The specified I/O operation on %hs was not completed before the time-out period expired.Server name: *Server address: *:*Connection type: Wsk*")
        {
            $normalizedEvent.NormalizedMessage="The network connection failed.Error: {Device Timeout}The specified I/O operation on %hs was not completed before the time-out period expired.Server name: <ServerName>Server address: <IpAddress>:<Port>Connection type: WskGuidance:This indicates a problem with the underlying network or transport, such as with TCP/IP, and not with SMB. A firewall that blocks port 445 or 5445 can also cause this issue."
        }
        elseif($normalizedEvent.RawMessage -like "The Virtual Machine Management Service failed to setup the listen socket for Virtual Machine migration connections for address '*': The requested address is not valid in its context. (0x80072741).*")
        {
            $normalizedEvent.NormalizedMessage="The Virtual Machine Management Service failed to setup the listen socket for Virtual Machine migration connections for address '<IpAddress>': The requested address is not valid in its context. (0x80072741)."
        }
        elseif($normalizedEvent.RawMessage -like "DM operation add for the virtual machine '*' failed with error: Generic failure (0x80041001)  (Virtual machine ID*).*")
        {
            $normalizedEvent.NormalizedMessage="DM operation add for the virtual machine '<VMName>' failed with error: Generic failure (0x80041001)  (Virtual machine ID <VMGUID>)."
        }
        elseif($normalizedEvent.RawMessage -like "An attempt to acquire a credential handle failed.Error: A specified logon session does not exist. It may already have been terminated.Security status: *User name: Logon ID: *Serrver name: \*")
        {
            $normalizedEvent.NormalizedMessage="An attempt to acquire a credential handle failed.Error: A specified logon session does not exist. It may already have been terminated.Security status: <StatusCode>User name: Logon ID: <LogonId>Serrver name: \<ServerName>"
        }
        else
        {
            $normalizedEvent.NormalizedMessage=$normalizedEvent.RawMessage    
        }

        $normalizedEvent
    }
}

function Get-TemplatedEvent()
{
    begin
    {
    }
    process
    {
        $event=$_
        #[xml]$eventXML=$event.ToXml()
        
        $providerEvent=(Get-WinEvent -ComputerName $event.MachineName -ListProvider $event.ProviderName).Events | Where-Object {$_.ID -eq $event.ID}
        [xml]$template=$providerEvent.Template
        $eventMessageTemplate=$providerEvent.Description

        $ns = New-Object Xml.XmlNamespaceManager $template.NameTable;
        $ns.AddNamespace("t","http://schemas.microsoft.com/win/2004/08/events")

        $dataElements=$template.SelectNodes("/t:template/t:data",$ns)

        for($i=1;$i -lt $dataElements.Count+1;$i++)
        {
            $eventMessageTemplate=$eventMessageTemplate.Replace("%$i",$dataElements[$i-1].Attributes["name"].Value)
        }

        $eventMessageTemplate

    }
}

Function Parse-WindowsEvent
{
    begin
    {}
    process
    {
        $event=$_
        
        if($event.ProviderName -eq "Application Error")
        {
            $event | Parse-ApplicationErrorEvent    
        }
        elseif($event.ProviderName -eq "Application Hang")
        {
            $event | Parse-ApplicationHangEvent
        }
        elseif($event.ProviderName -eq ".NET Runtime")
        {
            $event | Parse-NetRuntimeEvent
        }
    }    
}

function Parse-ApplicationErrorEvent()
{
    begin
    {}
    process
    {
        $event=$_
        [xml]$eventXML=$event.ToXml()

        $ns = New-Object Xml.XmlNamespaceManager $eventXML.NameTable;
        $ns.AddNamespace("t","http://schemas.microsoft.com/win/2004/08/events/event")

        $dataElements=($eventXML.SelectNodes("/t:Event/t:EventData/t:Data/text()",$ns)).Value

        $parsedEvent=New-Object -TypeName PSObject
        $parsedEvent | Add-Member -MemberType NoteProperty -Name MachineName -Value $event.MachineName
        $parsedEvent | Add-Member -MemberType NoteProperty -Name ProviderName -Value $event.ProviderName
        $parsedEvent | Add-Member -MemberType NoteProperty -Name RecordId -Value $event.RecordId
        $parsedEvent | Add-Member -MemberType NoteProperty -Name Id -Value $event.Id
        $parsedEvent | Add-Member -MemberType NoteProperty -Name TimeCreated -Value $event.TimeCreated
        $parsedEvent | Add-Member -MemberType NoteProperty -Name LevelDisplayName -Value $event.LevelDisplayName
        $parsedEvent | Add-Member -MemberType NoteProperty -Name ApplicationName -Value $dataElements[0]
        $parsedEvent | Add-Member -MemberType NoteProperty -Name ApplicationVersion -Value $dataElements[1]
        $parsedEvent | Add-Member -MemberType NoteProperty -Name ModuleName -Value $dataElements[3]
        $parsedEvent | Add-Member -MemberType NoteProperty -Name ModuleVersion -Value $dataElements[4]
        $parsedEvent | Add-Member -MemberType NoteProperty -Name ExceptionCode -Value $dataElements[6]
        $parsedEvent | Add-Member -MemberType NoteProperty -Name ApplicationPath -Value $dataElements[10]
        $parsedEvent | Add-Member -MemberType NoteProperty -Name ModulePath -Value $dataElements[11]

        $parsedEvent
    }
}

function Parse-ApplicationHangEvent()
{
    begin
    {}
    process
    {
        $event=$_
        [xml]$eventXML=$event.ToXml()

        $ns = New-Object Xml.XmlNamespaceManager $eventXML.NameTable;
        $ns.AddNamespace("t","http://schemas.microsoft.com/win/2004/08/events/event")

        $dataElements=($eventXML.SelectNodes("/t:Event/t:EventData/t:Data/text()",$ns)).Value

        $parsedEvent=New-Object -TypeName PSObject
        $parsedEvent | Add-Member -MemberType NoteProperty -Name MachineName -Value $event.MachineName
        $parsedEvent | Add-Member -MemberType NoteProperty -Name ProviderName -Value $event.ProviderName
        $parsedEvent | Add-Member -MemberType NoteProperty -Name RecordId -Value $event.RecordId
        $parsedEvent | Add-Member -MemberType NoteProperty -Name Id -Value $event.Id
        $parsedEvent | Add-Member -MemberType NoteProperty -Name TimeCreated -Value $event.TimeCreated
        $parsedEvent | Add-Member -MemberType NoteProperty -Name LevelDisplayName -Value $event.LevelDisplayName
        $parsedEvent | Add-Member -MemberType NoteProperty -Name ApplicationName -Value $dataElements[0]
        $parsedEvent | Add-Member -MemberType NoteProperty -Name ApplicationVersion -Value $dataElements[1]
        $parsedEvent | Add-Member -MemberType NoteProperty -Name ApplicationPath -Value $dataElements[5]
        

        $parsedEvent
    }
}

function Parse-NetRuntimeEvent()
{
    begin
    {}
    process
    {
        $event=$_
        [xml]$eventXML=$event.ToXml()

        $ns = New-Object Xml.XmlNamespaceManager $eventXML.NameTable;
        $ns.AddNamespace("t","http://schemas.microsoft.com/win/2004/08/events/event")

        $dataElements=($eventXML.SelectNodes("/t:Event/t:EventData/t:Data/text()",$ns)).Value

        $parsedEvent=New-Object -TypeName PSObject
        $parsedEvent | Add-Member -MemberType NoteProperty -Name MachineName -Value $event.MachineName
        $parsedEvent | Add-Member -MemberType NoteProperty -Name ProviderName -Value $event.ProviderName
        $parsedEvent | Add-Member -MemberType NoteProperty -Name RecordId -Value $event.RecordId
        $parsedEvent | Add-Member -MemberType NoteProperty -Name Id -Value $event.Id
        $parsedEvent | Add-Member -MemberType NoteProperty -Name TimeCreated -Value $event.TimeCreated
        $parsedEvent | Add-Member -MemberType NoteProperty -Name LevelDisplayName -Value $event.LevelDisplayName
        $parsedEvent | Add-Member -MemberType NoteProperty -Name ApplicationName -Value $event.Message.Split("`r`n")[0].Replace("Application: ","")
        $parsedEvent | Add-Member -MemberType NoteProperty -Name FrameworkVersion -Value $event.Message.Split("`r`n")[1].Replace("Framework Version: ","")
        $parsedEvent | Add-Member -MemberType NoteProperty -Name ExceptionStack -Value $dataElements.Substring($dataElements.IndexOf("Exception"),$dataElements.Length-($dataElements.IndexOf("Exception"))).Replace("`r","").Replace("`n","")
        

        $parsedEvent
    }
}